It's in the DBGMCU_IDCODE register. check the reference manual for your chip.

    uint8_t len = 0;

 

    char devidString[128] = {0};
 

    uint32_t idcode = DBGMCU->IDCODE & 0xFFF;
 

    switch (idcode)
 

    {
 

    case 0x410: len += sprintf(devidString+len, 'stm32f1xx medium-density'); break;
 

    case 0x411: len += sprintf(devidString+len, 'stm32f2xx'); break;
 

    case 0x412: len += sprintf(devidString+len, 'stm32f1xx low-density'); break;
 

    case 0x413: len += sprintf(devidString+len, 'stm32f405/407xx and stm32f415/417xx'); break;
 

    case 0x414: len += sprintf(devidString+len, 'stm32f1xx high-density'); break;
 

    case 0x415: len += sprintf(devidString+len, 'stm32l4xx'); break;
 

    case 0x416: len += sprintf(devidString+len, 'stm32l1xx medium-density'); break;
 

    case 0x417: len += sprintf(devidString+len, 'stm32l0xx'); break;
 

    case 0x418: len += sprintf(devidString+len, 'stm32f1xx connectivity line'); break;
 

    case 0x419: len += sprintf(devidString+len, 'stm32f4xx high-density'); break;
 

    case 0x420: len += sprintf(devidString+len, 'stm32f1xx value line'); break;
 

    case 0x421: len += sprintf(devidString+len, 'stm32f446xx'); break;
 

    case 0x422: len += sprintf(devidString+len, 'stm32f3xx'); break;
 

    case 0x423: len += sprintf(devidString+len, 'stm32f4xx low power'); break;
 

    case 0x425: len += sprintf(devidString+len, 'stm32l0xx cat. 2'); break;
 

    case 0x427: len += sprintf(devidString+len, 'stm32l1xx medium-density/plus'); break;
 

    case 0x428: len += sprintf(devidString+len, 'stm32f1xx value line high-density'); break;
 

    case 0x429: len += sprintf(devidString+len, 'stm32l1xx cat. 2'); break;
 

    case 0x430: len += sprintf(devidString+len, 'stm32f1xx xl-density'); break;
 

    case 0x431: len += sprintf(devidString+len, 'stm32f411re'); break;
 

    case 0x432: len += sprintf(devidString+len, 'stm32f37x'); break;
 

    case 0x433: len += sprintf(devidString+len, 'stm32f4xx de'); break;
 

    case 0x434: len += sprintf(devidString+len, 'stm32f4xx dsi'); break;
 

    case 0x435: len += sprintf(devidString+len, 'stm32l43x'); break;
 

    case 0x436: len += sprintf(devidString+len, 'stm32l1xx high-density'); break;
 

    case 0x437: len += sprintf(devidString+len, 'stm32l152re'); break;
 

    case 0x438: len += sprintf(devidString+len, 'stm32f334'); break;
 

    case 0x439: len += sprintf(devidString+len, 'stm32f3xx small'); break;
 

    case 0x440: len += sprintf(devidString+len, 'stm32f0xx'); break;
 

    case 0x441: len += sprintf(devidString+len, 'stm32f412'); break;
 

    case 0x442: len += sprintf(devidString+len, 'stm32f09x'); break;
 

    case 0x444: len += sprintf(devidString+len, 'stm32f0xx small'); break;
 

    case 0x445: len += sprintf(devidString+len, 'stm32f04x'); break;
 

    case 0x446: len += sprintf(devidString+len, 'stm32f303 high-density'); break;
 

    case 0x447: len += sprintf(devidString+len, 'stm32l0xx cat. 5'); break;
 

    case 0x448: len += sprintf(devidString+len, 'stm32f0xx can'); break;
 

    case 0x449: len += sprintf(devidString+len, 'stm32f74xxx/stm32f75xxx'); break;
 

    case 0x450: len += sprintf(devidString+len, 'stm32h7xxx'); break;
 

    case 0x451: len += sprintf(devidString+len, 'stm32f76xxx/stm32f77xxx'); break;
 

    case 0x452: len += sprintf(devidString+len, 'stm32f72xxx/stm32f73xxx'); break;
 

    case 0x457: len += sprintf(devidString+len, 'stm32l011'); break;
 

    case 0x458: len += sprintf(devidString+len, 'stm32f410'); break;
 

    case 0x463: len += sprintf(devidString+len, 'stm32f413'); break;
 

    default: len += sprintf(devidString+len, 'unknown device\r\n');
 

    }
    uint32_t revCode = (DBGMCU->IDCODE & DBGMCU_IDCODE_REV_ID_Msk) >> DBGMCU_IDCODE_REV_ID_Pos;

 

    switch (revCode)
 

    {
 

    case 0x1000: len += sprintf(devidString+len, '  Revision A\r\n'); break;
 

    case 0x1001: len += sprintf(devidString+len, '  Revision Z\r\n'); break;
 

    }
/*

          For example, it is read as RevA -> 0x1000, Cat 2 revZ -> 0x1001, rev1 -> 0x1003, rev2 ->0x1007, revY -> 0x100F for STM32F405/407xx and STM32F415/417xx devices

 

          For example, it is read as RevA -> 0x1000, Cat 2 revY -> 0x1003, rev1 -> 0x1007, rev3 ->0x2001 for STM32F42xxx and STM32F43xxx devices
 

          For example, it is read as RevZ -> 0x1000, Cat 2 revA -> 0x1001 for STM32F401xB/C devices
 

          For example, it is read as RevA -> 0x1000, Cat 2 revZ -> 0x1001 for STM32F401xD/E devices
 

          For example, it is read as RevA -> 0x1000 for STM32F411xx,STM32F413/423xx,STM32F469/423xx, STM32F446xx and STM32F410xx devices
 

          For example, it is read as RevZ -> 0x1001, Cat 2 revB -> 0x2000, revC -> 0x3000 for STM32F412xx devices
*/

    printf('%s', devidString);